
#ifndef QRREADER_H
#define QRREADER_H

#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <vector>
#include <QImage>
#include <cmath>

#include "center.h"

using namespace cv;
using namespace std;

#define VERSION_7  42232  // 001010010011111000
#define VERSION_8  63108  // 001111011010000100
#define VERSION_9  157028 // 100110010101100100
#define VERSION_10 208020 // 110010110010010100
#define VERSION_11 114548 // 011011111101110100
#define VERSION_12 72588  // 010001101110001100
#define VERSION_13 231532 // 111000100001101100

#define L_0 30660 // 111011111000100
#define L_1 29427 // 111001011110011
#define L_2 32170 // 111110110101010
#define L_3 30877 // 111100010011101
#define L_4 26159 // 110011000101111
#define L_5 25368 // 110001100011000
#define L_6 27713 // 110110001000001
#define L_7 26998 // 110100101110110

#define M_0 21522 // 101010000010010
#define M_1 20773 // 101000100100101
#define M_2 24188 // 101111001111100
#define M_3 23371 // 101101101001011
#define M_4 17913 // 100010111111001
#define M_5 16590 // 100000011001110
#define M_6 20375 // 100111110010111
#define M_7 19104 // 100101010100000

#define Q_0 13663 // 011010101011111
#define Q_1 12392 // 011000001101000
#define Q_2 16177 // 011111100110001
#define Q_3 14854 // 011101000000110
#define Q_4 9396  // 010010010110100
#define Q_5 8579  // 010000110000011
#define Q_6 11994 // 010111011011010
#define Q_7 11245 // 010101111101101

#define H_0 5769  // 001011010001001
#define H_1 5054  // 001001110111110
#define H_2 7399  // 001110011100111
#define H_3 6608  // 001100111010000
#define H_4 1890  // 000011101100010
#define H_5 597   // 000001001010101
#define H_6 3340  // 000110100001100
#define H_7 2107  // 000100000111011

#define NUMERIC_MODE       1 //0001
#define ALPHA_NUMERIC_MODE 2 //0010
#define BINARY_MODE        4 //0100
#define JAPANESE_MODE      8 //1000

class qrReader
{

    public:
        qrReader ();
        void readQrCode (QImage *m);

    private:
        float angle;
        int pixelProportion;
        int versionINFO;
        int seed[5];
        int seed2[7][3];
        char eccLevel;
        int maskPatern;

        vector<int> dataBlocks;

        center origin;
        center upperLeftCenter;
        center upperRightCenter;
        center lowerLeftCenter;

        int determinePixelProportion (QImage *m);
        int checkVersion (center c1, center c2, center c3, QImage* m);
        int checkExactVersion (center c1, center c2, QImage* m);

        void findCenters (QImage *m);
        center selectBestCenter (vector<center> centerList);
        void calculateAngle ();
        void adjustImage(QImage *m);
        vector<center> checkHorizontalUpLeft (int rowStart, int rowEnd, QImage *m);
        vector<center> checkHorizontalDownLeft (int rowStart, int rowEnd, QImage *m);
        vector<center> checkHorizontalUpRight (int rowStart, int rowEnd, QImage *m);
        bool crossCheckVertical (int startRow, int startCol, QImage* m);
        bool checkRatio (int m[]);

        void findTimming (center c1, center c2, center c3, QImage* m);
        void findFormat (center c1, center c2, center c3, QImage* m);
        void findAlignments (center c, QImage* m);

        void unMask (int row, int col, QImage* m);
        vector<int> getDataBlocks (center c, QImage* m);
        vector<int> correctDataBlocks (vector<int> dataBlocks);
        String decodeDataBlocks ();

        String decodeNumeric (int sizeDataLenght, int *numBlock);
        String decodeAlnum (int sizeDataLenght, int *numBlock);
        String decodeBinary (int sizeDataLenght, int *numBlock);
        String decodeJapanese (int sizeDataLenght, int *numBlock);

        bool isPixelBlack (int row, int col, QImage* m);
        void paintPixel (int row, int col, QRgb color, QImage* m);
        void reversePixel (int row, int col, QImage* m);
        bool isPattern (int row, int col, QImage* m);

};

#endif // QRREADER_H


